﻿//Copyright (c) Chris Pietschmann 2013 (http://pietschsoft.com)
//Licensed under the GNU Library General Public License (LGPL)
//License can be found here: http://easypatterns.codeplex.com/license

using System;

namespace EasyPatterns.Factory
{
    /// <summary>
    /// A Factory Pattern base class.
    /// </summary>
    /// <typeparam name="TCreateType">The Type that the Factory will Create.</typeparam>
    /// <typeparam name="TReturnType">The Type that the Factory will Return.</typeparam>
    public abstract class Factory<TCreateType, TReturnType> : IFactory<TReturnType>
        where TCreateType : TReturnType
    {
        protected abstract TCreateType CreateInstance();

        /// <summary>
        /// Creates a new instnace of the specified Type.
        /// </summary>
        /// <returns>An instance of the specified Type.</returns>
        public TReturnType Create()
        {
            return this.CreateInstance();
        }

        /// <summary>
        /// Creates a new instance of the specified Type.
        /// </summary>
        /// <returns>An instance of the specified Type.</returns>
        object IFactory.Create()
        {
            return this.Create();
        }
    }

    /// <summary>
    /// A base class for implementing the Factory Pattern
    /// </summary>
    public static class Factory
    {
        #region Static Methods

        /// <summary>
        /// Creates a new Factory using the specified expression.
        /// </summary>
        /// <typeparam name="T">The Type the factory will create.</typeparam>
        /// <param name="createInstanceExpression">The "Create Instance" expression to use within the Factory for creating new instances of the specified Type.</param>
        /// <returns>An IFactory instance.</returns>
        public static IFactory<T> CreateFactory<T>(Func<T> createInstanceExpression)
        {
            return new LambdaFactory<T>(createInstanceExpression);
        }

        /// <summary>
        /// Creates a new Factory for the specified Type.
        /// </summary>
        /// <typeparam name="T">The Type the factory will create.</typeparam>
        /// <returns>An IFactory instance.</returns>
        public static IFactory<T> CreateFactory<T>()
            where T: new()
        {
            return new SimpleFactory<T>();
        }

        /// <summary>
        /// Creates a new Factory for the specified Type, using the specified parameters for constructing a "Create Instance" expression.
        /// </summary>
        /// <typeparam name="T">The Type the factory will create.</typeparam>
        /// <param name="parameters"></param>
        /// <returns>An IFactory instance.</returns>
        public static IFactory<T> CreateFactory<T>(params object[] parameters)
        {
            return new LambdaFactory<T>(() => {
                return (T)Activator.CreateInstance(typeof(T), parameters);
            });
        }

        #endregion
    }
}
